﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using ComponentSystem;
using Cysharp.Threading.Tasks;
using UnityEngine;

namespace DataCenterSystem.EasySave3
{
    /// <summary>
    /// 存储组件基类
    /// </summary>
    public partial class BaseSave_Com : ComponentWithId
    {
        /// <summary>
        /// 存储的配置
        /// </summary>
        protected ES3Settings es3Settings = new ES3Settings { autoCacheDefaultFile = false };
        /// <summary>
        /// 缓存key值，用ConcurrentDictionary的原因是因为线程安全且高效，value为空，不用存内容
        /// </summary>
        protected ConcurrentDictionary<string,string> cachedKeys = new ConcurrentDictionary<string,string>();
    }

    public partial class BaseSave_Com
    {
        /// <summary>
        /// 检查ES3场景管理器
        /// </summary>
        protected async UniTask Check_ES3SceneManager()
        {
            //获取当前场景的唯一ID
            int sceneId  = UnityEngine.SceneManagement.SceneManager.GetActiveScene().GetHashCode();
            
            GameObject mgrCache = UnityEngine.GameObject.Find("[DataCenterSystem]Es3SystemAddon[sceneId]");
            
            if(mgrCache!=null) return;
            
            UnityEngine.GameObject obj = new UnityEngine.GameObject("[DataCenterSystem]Es3SystemAddon[sceneId]");
            obj.AddComponent<ES3ReferenceMgr>();
        }
        
        /// <summary>
        /// 添加或更新数据
        /// </summary>
        public virtual async UniTask AddOrUpdateData<T>(string key, T data)
        {
            await Check_ES3SceneManager();
            
            if (string.IsNullOrEmpty(key) || data == null) return;
            
            ES3.Save(key, data, es3Settings);
            cachedKeys.AddOrUpdate(key, key, (_, _) => key);
        }

        /// <summary>
        /// 读取数据
        /// </summary>
        public virtual async UniTask<T> LoadData<T>(string key)
        {
            await Check_ES3SceneManager();
            
            if (string.IsNullOrEmpty(key) || !await ContainsKey(key))
            {
                throw new Exception($"AddOrUpdateData() 读取异常 key: {key}");
            }

            await LoadData_Hook(key);
            
            return ES3.Load<T>(key, es3Settings);
        }

        /// <summary>
        /// 读取数据钩子
        /// </summary>
        protected virtual async UniTask LoadData_Hook(string key)
        {
            
        }

        /// <summary>
        /// 删除数据
        /// </summary>
        public virtual async UniTask<bool> DeletData(string key)
        {
            await Check_ES3SceneManager();
            
            //如果不存在，则视为删除完成
            if (!await ContainsKey(key)) return true;

            if (!await DeletData_Hook(key)) return false;
            
            try
            {
                cachedKeys.TryRemove(key, out _);
                ES3.DeleteKey(key, es3Settings);
                return true;
            }
            catch (Exception e)
            {
                UnityEngine.Debug.LogError($"DeletData() 删除数据异常 key: {key} -- e: {e.Message}");
                return false;
            }
        }

        /// <summary>
        /// 删除数据钩子
        /// </summary>
        protected virtual async UniTask<bool> DeletData_Hook(string key)
        {
            return true;
        }

        /// <summary>
        /// 检查是否存在key
        /// </summary>
        public virtual async UniTask<bool> ContainsKey(string key)
        {
            await Check_ES3SceneManager();
            
            return ES3.KeyExists(key, es3Settings);
        }

        /// <summary>
        /// 清除所有数据
        /// </summary>
        public virtual async UniTask<bool> ClearSave()
        {
            await Check_ES3SceneManager();
            
            try
            {
                ES3.DeleteFile(es3Settings);
                cachedKeys.Clear();
                return true;
            }
            catch (Exception e)
            {
                UnityEngine.Debug.LogError($"ClearSave() 清除所有数据异常 -- e: {e.Message}");
                return false;
            }
        }

        /// <summary>
        /// 设置保存路径
        /// </summary>
        public virtual async UniTask Setting_SavePath(ES3.Directory pathEnum, string path = "")
        {
            if (pathEnum == ES3.Directory.CustomPath)
            {
                es3Settings.directory = pathEnum;
                es3Settings.customPath = path;
            }else
                es3Settings.directory = pathEnum;
        }
    }
}